<template>
  <div class="stream">
    <video ref="ctrl" class="ctrl" width="640" height="480" controls></video>
  </div>
</template>

<script setup>
const ctrl = ref(null);
const mediaSource = new MediaSource();
let cVal = 1;
let totalSegments = 4;
let lenVal = 5524488 / totalSegments;

// 新建一个 sourceBuffer
let sourceBuffer = null;
// 这个奇怪的字符串后面再解释
const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';

function requset(start, finish) {
  return new Promise((resolve) => {
    setTimeout(() => {
      fetch("/frag_bunny.mp4", {
        headers: {
          responseType: "arraybuffer",
          Range: `bytes=${start}-${finish}`,
        },
      }).then((r) => resolve(r.arrayBuffer()));
    }, Math.random() * 1000 + 400);
  });
}

// total 5524488
function load(start = 0, callback) {
  let finish = start + lenVal;
  if (start > 0) ++start;

  console.log(start, finish, cVal);
  if (typeof callback === "function") {
    return callback(start, finish);
  } else {
    requset(start, finish).then((r) => {
      sourceBuffer.appendBuffer(r);
      if (cVal > 1) ctrl.value.play();
    });
  }
}

const helper = () => {
  return ctrl.value.currentTime / ctrl.value.duration;
};

const updater = () => {
  const hpVal = (cVal / totalSegments) * 0.6;
  if (cVal >= totalSegments) {
    ctrl.value.removeEventListener("timeupdate", updater);
  } else {
    console.log("timeupdate", cVal);
    if (helper() >= hpVal) load((++cVal - 1) * lenVal);
  }
};

onMounted(() => {
  ctrl.value.src = URL.createObjectURL(mediaSource);

  mediaSource.addEventListener("sourceopen", (e) => {
    sourceBuffer = e.target.addSourceBuffer(mime);

    load((cVal - 1) * lenVal);

    ctrl.value.addEventListener("timeupdate", updater);
    sourceBuffer.addEventListener("updateend", (_) => {
      // const all = queue.map((fn) => fn());
      // queue = [];
      // Promise.allSettled(all).then((r) => {
      //   appendSegment(r.map((v) => v.value));
      // });

      const hlVal = mediaSource.readyState == "open";
      if (cVal >= totalSegments) {
        if (hlVal) mediaSource.endOfStream();
      }
    });

    function appendSegment(list) {
      if (list.length) {
        sourceBuffer.appendBuffer(list.shift());
        setTimeout(() => appendSegment(list), 60);
      }
    }

    let queue = [];
    const hl = 1 / totalSegments;
    function creater(current) {
      return () => load((++cVal - 1) * lenVal, requset);
    }
    let seekVal = 0;
    
    ctrl.value.addEventListener("seeking", async (e) => {
      seekVal = Math.ceil(helper() / hl);
      let current = 0;
      for (let i = cVal; i < seekVal; i++) {
        // queue.push(creater(current++));
      }
    });
  });
});
</script>

<style lang="scss" scoped></style>
